home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
magazine
/
progjour
/
1991
/
06
/
alib
/
stream.asm
< prev
next >
Wrap
Assembly Source File
|
1991-08-21
|
10KB
|
462 lines
title stream i/o
include asm.inc
public fclose
public fopen
public fread
public fwrite
SIO_BUFSIZ equ 8192 ; stream io buffer size
stream_io_str struc
sio_position dd ? ; stream position
sio_offset dd ? ; buffer offset
sio_read_bc dw ? ; buffer byte count for reading
sio_write_bc dw ? ; buffer byte count for writing
sio_file_handle dw ? ; dos file handle
sio_buffer db SIO_BUFSIZ dup(?) ; stream buffer
stream_io_str ends
.data
extb ertx_disk_full
ertx_fopen_mode db 'Bad mode in fopen',0
ertx_out_of_handles db 'Out of stream handles',0
ertx_stream_handle db 'Bad stream handle',0
.data?
stream_pointers dd FOPEN_MAX dup(?)
.code
extn free,ms_dos,ms_dos_strerror,set_strerror,malloc
;; fclose
;
; entry BX stream handle
; exit Cf if error closing file or bad handle
; uses AX,BX
;
fclose proc
pushm di,si,es
call fwrite_flush ; write bytes left in stream buffer
jc fcl1 ; if disk full
call stream_struct_write ; access stream structure
jc fcl1 ; if bad handle
mov si,bx ; clear stream structure pointer
add si,si
add si,si
mov wptr stream_pointers[bp+si],NULL_POINTER
mov wptr stream_pointers[bp+si+2],NULL_POINTER
mov bx,es:sio_file_handle[di]
call free
mov ah,3Eh
call ms_dos_strerror
fcl1: popm es,si,di
ret
fclose endp
;; fopen
;
; entry AX mode, 'r' or 'w' to open for reading or writing
; DS:SI filename
; exit BX stream handle
; Cf if error
; uses AX
;
fopen proc
pushm cx,dx,di,es
cmp ax,'r'
mov dx,3D00h
je fop1 ; if opening file for reading only
cmp ax,'w'
jne fop3 ; if not open for write (unknown mode)
mov dh,3Ch
mov cx,0
fop1: mov ax,dx
mov dx,si
call ms_dos_strerror ; (ms dos with error handling)
jc fop2 ; if file open failed
mov dx,ax
call malloc_stream
jc fop4 ; if no memory or stream handles
mov al,0 ; zero stream structure (except for
mov cx,sio_buffer ; buffer space)
push di
rep stosb
pop di
mov es:sio_file_handle[di],dx
clc
fop2: popm es,di,dx,cx
ret
fop3: lea ax,ertx_fopen_mode ; *Bad mode in fopen*
call set_strerror
jmp fop2
fop4: mov ah,3Eh ; close file, no memory for structure
mov bx,dx
call ms_dos
stc
jmp fop2
fopen endp
;; fread
;
; entry BX stream handle
; CX byte count
; ES:DI destination pointer
; exit AX actual byte count (!=CX for EOF)
; DI updated
; Cf if error
;
fread proc
pushm di,bx,cx,dx,si,ds
cmp bx,stdin
je fre3 ; if special handle, standard input
call stream_struct_read
jc fre4
mov bx,si
fre1: jcxz fre4 ; if read finished
mov ax,wptr sio_position[bx]; compute stream position w/i buffer
mov dx,wptr sio_position[bx+2]
sub ax,wptr sio_offset[bx]
sbb dx,wptr sio_offset[bx+2]
jnz fre2 ; if buffer not w/i 64k of position
mov dx,sio_read_bc[bx] ; get number of bytes to end of buffer
sub dx,ax
jbe fre2 ; if stream position not in buffer
lea si,sio_buffer[bx]
add si,ax
call rep_movsb_limit
add wptr sio_position[bx],dx ; update stream position
adc wptr sio_position[bx+2],0
jmp fre1
fre2: call fread_primitive ; fill stream buffer
jbe fre4 ; if error (Cf==1) or EOF (Zf==1)
jmp fre1 ; else successful
fre3: mov ah,3Fh ; read from special handle stdin
mov dx,es
mov ds,dx
mov dx,di
call ms_dos_strerror
jc fre4
add di,ax ; (should not set Cf unless DI wraps)
fre4: popm ds,si,dx,cx,bx,ax
jc fre5 ; if error
neg ax ; else return bytes read
add ax,di
clc
fre5: ret
fread endp
;; fread primitive
;
; entry DS:BX stream structure
; exit AX bytes read from file
; Cf if error (Zf unknown)
; Zf if end of file
; uses SI
;
fread_primitive proc
pushm bx,cx,dx
mov si,bx
mov ax,4200h ; position file
mov bx,sio_file_handle[si]
mov dx,wptr sio_position[si]
mov cx,wptr sio_position[si+2]
call ms_dos_strerror
jc frp1 ; if error position file
mov wptr sio_offset[si],ax
mov wptr sio_offset[si+2],dx
mov sio_read_bc[si],0
mov ah,3Fh ; read file
mov cx,size sio_buffer
lea dx,sio_buffer[si]
call ms_dos_strerror
jc frp1 ; if read error
mov sio_read_bc[si],ax
or ax,ax ; set Zf for end of file
frp1: popm dx,cx,bx
ret
fread_primitive endp
;; fwrite
;
; entry BX stream handle
; CX byte count
; DS:SI source pointer
; exit AX bytes written
; SI updated
; Cf if error
;
fwrite proc
pushm si,cx,dx,di,es
cmp bx,stdout ; check for special streams
je fwr2 ; if writing to standard out
cmp bx,stderr
je fwr2 ; if writing to standard error
call fwrite_flush_maybe ; flush buffer in event of seek
jc fwr3 ; if bad handle or disk full
call stream_struct_write ; access stream structure
jc fwr3 ; if bad handle
fwr1: clc
jcxz fwr3 ; if write complete
mov ax,es:sio_write_bc[di] ; compute space left in stream buffer
mov dx,size sio_buffer
sub dx,ax
jb fwr3 ; if internal error (Cf=1)
push di ; copy to stream buffer
lea di,sio_buffer[di]
add di,ax
call rep_movsb_limit
pop di
add ax,dx ; update stream buffer byte count
mov es:sio_write_bc[di],ax ; and position
add wptr es:sio_position[di],dx
adc wptr es:sio_position[di+2],0
cmp ax,size sio_buffer ; check stream buffer level
jb fwr1 ; if not full
call fwrite_flush ; else write buffer to disk
jnc fwr1 ; if write successful
jmp fwr3 ; else disk full (Cf=1)
fwr2: mov ah,40h ; write standard output/error
mov dx,si
call ms_dos_strerror
jc fwr3 ; if write failed
add si,ax
fwr3: popm es,di,dx,cx,ax
jc fwr4 ; if error
neg ax ; else return bytes written
add ax,si
clc
fwr4: ret
fwrite endp
;; fwrite flush
;
; entry BX stream handle
; exit Cf if disk full, bad handle, or other error
; uses AX
;
fwrite_flush proc
pushm bx,cx,dx,si,ds
call stream_struct_read
jc fwf1 ; if bad handle
mov cx,sio_write_bc[si]
jcxz fwf1 ; if buffer empty (nothing to flush)
mov ax,4200h ; position file
mov bx,sio_file_handle[si]
mov dx,wptr sio_offset[si]
mov cx,wptr sio_offset[si+2]
call ms_dos_strerror
jc fwf1 ; if position failed
mov ah,40h ; write file
mov cx,sio_write_bc[si]
lea dx,sio_buffer[si]
call ms_dos_strerror
jc fwf1 ; if write failed
add wptr sio_offset[si],ax ; update buffer position
adc wptr sio_offset[si+2],0
mov sio_write_bc[si],0 ; clear output byte count
cmp ax,cx
je fwf1 ; if correct byte cnt written (Cf=0)
lea ax,ertx_disk_full ; else *Disk full*
call set_strerror
fwf1: popm ds,si,dx,cx,bx
ret
fwrite_flush endp
;; fwrite flush maybe
;
; entry BX stream handle
; exit Cf if bad handle or disk full
; uses AX,DX
;
fwrite_flush_maybe proc
pushm si,ds
call stream_struct_read
jc ffm2 ; if bad stream handle
mov ax,wptr sio_offset[si] ; compute buffer position
mov dx,wptr sio_offset[si+2]
add ax,sio_write_bc[si]
adc dx,0
cmp ax,wptr sio_position[si]
jne ffm1 ; if wrong position
cmp dx,wptr sio_position[si+2]
je ffm2 ; if right position
ffm1: call fwrite_flush
jc ffm2 ; if disk full
mov ax,wptr sio_position[si] ; reposition buffer
mov wptr sio_offset[si],ax
mov ax,wptr sio_position[si+2]
mov wptr sio_offset[si+2],ax
ffm2: popm ds,si
ret
fwrite_flush_maybe endp
;; malloc stream
;
; exit BX stream handle
; ES:DI stream structure
; Cf if no handles or memory left
; uses AX
;
malloc_stream proc
pushm cx,si
mov bx,stderr ; find free stream handle
mas1: inc bx
cmp bx,FOPEN_MAX
jae mas3 ; if no handles left
mov si,bx
add si,si
add si,si
les di,stream_pointers[bp+si]
mov ax,es
or ax,di
jnz mas1 ; if stream allocated
mov cx,size stream_io_str ; allocate memory for stream structure
call malloc
jc mas2 ; if no memory
mov wptr stream_pointers[bp+si],di
mov wptr stream_pointers[bp+si+2],es
mas2: popm si,cx
ret
mas3: lea ax,ertx_out_of_handles ; *Out of stream handles*
call set_strerror
jmp mas2
malloc_stream endp
;; rep movsb limit
;
; entry DS:SI source pointer
; ES:DI destination pointer
; CX byte count
; DX byte count limit
; exit SI,DI updated
; CX updated (nonzero if original DX<CX)
; DX actual number of bytes transfered (minimum of CX,DX)
;
rep_movsb_limit proc
push ax
cmp cx,dx ; DX is unsigned minimum of CX and DX
ja rmm1
mov dx,cx
rmm1: mov ax,cx ; this procedure implements a smart
sub ax,dx ; "rep movsb" instruction. the
mov cx,dx ; difference is it moves the minimum
rep movsb ; number of bytes specified in CX or
mov cx,ax ; DX. CX is updated normally; DX has
pop ax ; the actual number of bytes moved.
ret
rep_movsb_limit endp
;; stream struct read
;
; entry BX stream handle
; exit DS:SI stream structure
; Cf if bad handle
; uses AX
;
stream_struct_read proc
cmp bx,FOPEN_MAX
jae rss1 ; if handle too large
mov si,bx
add si,si
add si,si
lds si,stream_pointers[bp+si]
mov ax,ds
or ax,si
jz rss1 ; if inactive stream
ret
rss1: lea ax,ertx_stream_handle ; *Bad stream handle*
jmp set_strerror
stream_struct_read endp
;; stream struct write
;
; entry BX stream handle
; exit ES:DI stream structure
; Cf if bad handle
; uses AX
;
stream_struct_write proc
cmp bx,FOPEN_MAX
jae wss1 ; if handle too large
mov di,bx
add di,di
add di,di
les di,stream_pointers[bp+di]
mov ax,es
or ax,di
jz wss1 ; if inactive stream
ret
wss1: lea ax,ertx_stream_handle ; *Bad stream handle*
jmp set_strerror
stream_struct_write endp
end